home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Apple Macintosh Developer Technical Support
- **
- ** Program: listcontrol.c
- ** Written by: Eric Soldan
- **
- ** Copyright © 1991 Apple Computer, Inc.
- ** All rights reserved.
- */
-
- /*
- **
- ** To create a List control, you only need a single call. For example:
- **
- ** list = CLNew(rViewCtl, Resource ID of view control for List control.
- ** numRows, Number of rows to create List with.
- ** numCols, Number of columns to create List with.
- ** cellHeight,
- ** cellWidth,
- ** theLProc, Custom List procedure resource ID.
- ** window, Window to hold List control.
- ** clHScroll | blBrdr | clActive Horizontal scrollbar, active List.
- ** );
- **
-
- ** If the CLNew call succeeds, you then have a List control in your
- ** window. It will be automatically disposed of when you close the window.
- ** If you don't waht this to happen, then you can detatch it from the
- ** view control which owns it. To do this, you would to the following:
- **
- ** viewCtl = CLViewFromList(theListHndl);
- ** if (viewCtl) SetCRefCon(viewCtl, nil);
- **
- ** The view control keeps a reference to the List record in the refCon.
- ** If the refCon is cleared, then the view control does nothing. So, all that
- ** is needed to detatch a List record from a view control is to set the
- ** view control's refCon nil. Now if you close the window, you will still
- ** have the List record.
- **
- **
- ** To remove a List control completely from a window, just dispose of the view
- ** control that holds the List record. To do this, just do something like the below:
- **
- ** DisposeControl(CLViewFromList(theListHndl));
- **
- ** This completely disposes of the List control.
- **
- **
- ** Events for the List record are handled nearly automatically. Just make the
- ** following call:
- **
- ** CLClick(eventPtr, &dblClick);
- **
- ** If the event was handled, true is returned. If the event is false, then the
- ** event doesn't belong to a List control, and further processing of the event
- ** should be done.
- **
- */
-
-
- extern short gPrintPage; /* Non-zero means we are printing. */
-
- /*****************************************************************************/
-
-
-
- #ifndef __CONTROLS__
- #include <Controls.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __LISTCONTROL__
- #include "ListControl.h"
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __PACKAGES__
- #include <Packages.h>
- #endif
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
-
-
- /*****************************************************************************/
-
-
-
- #define kListPosTextLen 32
-
- #define kPrevSel 16
- #define kLeftArrow 28
- #define kRightArrow 29
- #define kUpArrow 30
- #define kDownArrow 31
-
- typedef struct cdefRsrcJMP {
- long moveInst;
- long jsrInst;
- short jmpInst;
- long jmpAddress;
- } cdefRsrcJMP;
- typedef cdefRsrcJMP *cdefRsrcJMPPtr, **cdefRsrcJMPHndl;
-
-
-
- /*****************************************************************************/
-
-
-
- static long lastKeyTime;
- static char listPosText[kListPosTextLen];
- static short listPosTextLen;
- static short theViewID;
-
- static void CLBorderDraw(ListHandle listHndl);
- static pascal long CLCtl(short varCode, ControlHandle ctl, short msg, long parm);
- static pascal short MyIntlCompare(Ptr aPtr, Ptr bPtr, short aLen, short bLen);
-
-
-
-
- /*****************************************************************************/
-
-
-
- static ListHandle gFoundLHndl;
- /* Global value used to return info from the List control proc. */
-
- static ControlHandle gFoundViewCtl;
- /* Global value used to return info from the List control proc. */
-
-
-
- /*****************************************************************************/
- /*****************************************************************************/
- /*****************************************************************************/
-
-
-
- /* Activate this List record. Activation is not done by calling LActivate().
- ** The active control is indicated by the 2-pixel thick border around the
- ** List control. This allows all List controls in a window to display which
- ** cells are selected. This behavior can be overridden by calling LActivate()
- ** on the List record for List controls.
- ** Human interface dictates that only at most a single List control has this
- ** active border. For this reason, this function scans for other List
- ** controls in the window and removes the border from any other that it finds.
- */
-
- #pragma segment Controls
- void CLActivate(Boolean active, ListHandle listHndl)
- {
- WindowPtr window, oldPort;
- ControlHandle viewCtl;
- short oldDisplay, newDisplay;
- ListHandle list;
- CLDataHndl listData;
-
- if (listHndl) {
- window = (WindowPtr)(*listHndl)->port;
- for (viewCtl = nil;;) {
- viewCtl = CLNext(window, &list, viewCtl);
- if (!viewCtl) break;
- listData = (CLDataHndl)(*viewCtl)->contrlData;
- oldDisplay = (*listData)->mode;
- newDisplay = (oldDisplay & (0xFFFF - clActive));
- if (active)
- if (list == listHndl)
- newDisplay |= clActive;
- if (oldDisplay != newDisplay) {
- (*listData)->mode = newDisplay;
- GetPort(&oldPort);
- SetPort(window);
- CLBorderDraw(list);
- SetPort(oldPort);
- }
- }
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Controls
- void CLBorderDraw(ListHandle listHndl)
- {
- ControlHandle viewCtl;
- WindowPtr oldPort, listPort;
- short displayInfo;
- Rect rct;
- PenState oldPen;
- CLDataHndl listData;
-
- if (listHndl) {
- if (viewCtl = CLViewFromList(listHndl)) {
- GetPort(&oldPort);
- SetPort(listPort = (*listHndl)->port);
- GetPenState(&oldPen);
- PenNormal();
- listData = (CLDataHndl)(*viewCtl)->contrlData;
- displayInfo = (*listData)->mode;
- rct = (*listHndl)->rView;
- InsetRect(&rct, -1, -1);
- FrameRect(&rct);
- if (displayInfo & clShowActive) {
- rct = (*listHndl)->rView;
- InsetRect(&rct, -4, -4);
- if ((*listHndl)->vScroll) rct.right += 15;
- if ((*listHndl)->hScroll) rct.bottom += 15;
- PenSize(2, 2);
- if ((listPort != FrontWindow()) || (!(displayInfo & clActive))) PenPat(qd.white);
- FrameRect(&rct);
- }
- SetPenState(&oldPen);
- SetPort(oldPort);
- }
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* This is called when a mouseDown occurs in the content of a window. It
- ** returns true if the mouseDown caused a List action to occur. Events
- ** that are handled include if the user clicks on a scrollbar that is
- ** associated with a List control.
- */
-
- #pragma segment Controls
- Boolean CLClick(EventRecord *event, short *dblClick)
- {
- WindowPtr oldPort, window;
- Point mouseLoc;
- ListHandle list;
- ControlHandle ctlHit, viewCtl;
- short part;
-
- *dblClick = false;
- lastKeyTime = 0;
-
- GetPort(&oldPort);
- SetPort(window = FrontWindow());
- mouseLoc = event->where;
- GlobalToLocal(&mouseLoc);
-
- if (CLFindCtl(window, event, &list, &ctlHit)) {
- /* See if the user clicked directly on the view control for a
- ** List record. If so, we definitely have some work to do.
- */
- if (CLFindActive(window) != list) CLActivate(true, list);
- /* If user clicked on List control other than the
- ** currently active control, then activate it.
- */
- *dblClick = LClick(mouseLoc, event->modifiers, list);
- SetPort(oldPort);
- return(true);
- }
-
- /* We didn't hit the view control for a List record, but don't give up yet.
- ** The user may be clicking on a related scrollbar. Let's find out...
- */
-
- if (part = FindControl(mouseLoc, window, &ctlHit)) {
- /* The user did click on a control. But is it a scrollbar
- ** for a List control? Stay tuned...
- */
- list = CLFromScroll(ctlHit, &viewCtl);
- if (list) { /* It was a related scrollbar. */
- CLActivate(true, list);
- LClick(mouseLoc, event->modifiers, list);
- SetPort(oldPort);
- return(true);
- }
- }
-
- SetPort(oldPort);
- return(false);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Controls
- pascal long CLCtl(short varCode, ControlHandle ctl, short msg, long parm)
- {
- #pragma unused (varCode)
-
- Rect viewRct;
- ListHandle list;
- WindowPtr thePort;
-
- if (list = (ListHandle)GetCRefCon(ctl)) viewRct = (*list)->rView;
- else SetRect(&viewRct, 0, 0, 0, 0);
-
- switch (msg) {
- case drawCntl:
- GetPort(&thePort);
- CLUpdate(thePort->visRgn, list);
- CLBorderDraw(list);
- break;
-
- case testCntl:
- if (PtInRect(*(Point *)&parm, &viewRct)) {
- gFoundViewCtl = ctl;
- gFoundLHndl = list;
- return(1);
- }
- return(0);
- break;
-
- case calcCRgns:
- case calcCntlRgn:
- if (msg == calcCRgns) parm &= 0x00FFFFFF;
- RectRgn((RgnHandle)parm, &viewRct);
- break;
-
- case initCntl:
- break;
-
- case dispCntl:
- if (list) {
- LDispose(list);
- DisposeHandle((Handle)(*ctl)->contrlData);
- }
- break;
-
- case posCntl:
- break;
-
- case thumbCntl:
- break;
-
- case dragCntl:
- break;
-
- case autoTrack:
- break;
- }
-
- return(0);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Controls
- ControlHandle CLCtlHit(void)
- {
- ControlHandle ctl;
-
- ctl = gFoundViewCtl;
- gFoundViewCtl = nil;
- return(ctl);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* Handle the event if it applies to the active List control. If some
- ** action occured due to the event, return true.
- */
-
- #pragma segment Controls
- Boolean CLEvent(EventRecord *event, short *dblClick)
- {
- *dblClick = false;
- if (event->what != mouseDown) return(false);
- return(CLClick(event, dblClick));
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Controls
- ListHandle CLFindActive(WindowPtr window)
- {
- ControlHandle viewCtl;
- ListHandle list;
- short display;
- CLDataHndl listData;
-
- if (!window) return(nil);
-
- for (viewCtl = nil;;) {
- viewCtl = CLNext(window, &list, viewCtl);
- if (!viewCtl) break;
- listData = (CLDataHndl)(*viewCtl)->contrlData;
- display = (*listData)->mode;
- if (display & clActive) break;
- }
- return(list);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* This determines if a List control was clicked on directly. This does
- ** not determine if a related scrollbar was clicked on. If a List
- ** control was clicked on, then true is returned, as well as the List
- ** handle and the handle to the view control.
- */
-
- #pragma segment Controls
- Boolean CLFindCtl(WindowPtr window, EventRecord *event,
- ListHandle *listHndl, ControlHandle *ctlHit)
- {
- WindowPtr oldPort;
- Point mouseLoc;
-
- if (window) {
- GetPort(&oldPort);
- SetPort(window);
- mouseLoc = event->where;
- GlobalToLocal(&mouseLoc);
- SetPort(oldPort);
-
- gFoundLHndl = nil;
- FindControl(mouseLoc, window, ctlHit);
- if (*listHndl = gFoundLHndl) return(true);
- }
-
- *ctlHit = nil;
- return(false);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* Find the List record that is related to the indicated scrollbar. */
-
- #pragma segment Controls
- ListHandle CLFromScroll(ControlHandle scrollCtl, ControlHandle *retCtl)
- {
- WindowPtr window;
- ControlHandle viewCtl;
- ListHandle list;
-
- window = (*scrollCtl)->contrlOwner;
-
- for (*retCtl = viewCtl = nil;;) {
- viewCtl = CLNext(window, &list, viewCtl);
- if (!viewCtl) return(nil);
- list = (ListHandle)GetCRefCon(viewCtl);
- if (
- ((*list)->vScroll == scrollCtl) ||
- ((*list)->hScroll == scrollCtl)
- ) {
- *retCtl = viewCtl;
- return(list);
- }
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Controls
- short CLInsert(ListHandle listHndl, char *data, short dataLen, short row, short col)
- {
- short loc;
- Point cell;
-
- if (!listHndl) return(-1);
-
- loc = CLRowOrColSearch(listHndl, data, dataLen, row, col);
-
- if (row == -1) {
- LAddRow(1, cell.v = loc, listHndl);
- cell.h = col;
- }
- else {
- LAddColumn(1, cell.h = loc, listHndl);
- cell.v = row;
- }
-
- LSetCell(data, dataLen, cell, listHndl);
- return(loc);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* See if the keypress event applies to the List control, and if it does,
- ** handle it and return true.
- */
-
- #pragma segment Controls
- Boolean CLKey(EventRecord *event)
- {
- WindowPtr window;
- ListHandle list;
- ControlHandle listCtl;
- short key, mode;
- Point cell, dcell;
- Rect bnds, visCells;
- CLDataHndl listData;
-
- if (list = CLFindActive(window = FrontWindow())) {
-
- listCtl = CLViewFromList(list);
- listData = (CLDataHndl)(*listCtl)->contrlData;
- mode = (*listData)->mode;
- if (!(mode & clKeyPos)) return(false);
-
- bnds = (*list)->dataBounds;
- if (bnds.top == bnds.bottom) return(true);
- if (bnds.left == bnds.right) return(true);
- /* The list is empty, so whatever was typed has been "handled". */
-
- cell.h = bnds.left;
- cell.v = bnds.top;
- key = event->message & charCodeMask;
-
- if ((key >= kLeftArrow) && (key <= kDownArrow)) {
- if (LGetSelect(true, &cell, list)) key -= kPrevSel;
- switch (key) {
- case kLeftArrow - kPrevSel:
- if (cell.h > bnds.left) --cell.h;
- break;
- case kRightArrow - kPrevSel:
- if (cell.h < bnds.left - 1) ++cell.h;
- break;
- case kUpArrow - kPrevSel:
- if (cell.v > bnds.top) --cell.v;
- break;
- case kDownArrow - kPrevSel:
- if (cell.v < bnds.bottom - 1) ++cell.v;
- break;
- case kLeftArrow:
- if (bnds.top < bnds.bottom - 1) return(true);
- /* With no previous selection, if the list has
- ** more than one row, we don't know which to use.
- ** Selection is indeterminate, so do nothing. */
- cell.v = bnds.top;
- cell.h = bnds.right - 1;
- break;
- case kRightArrow:
- if (bnds.top < bnds.bottom - 1) return(true);
- /* With no previous selection, if the list has
- ** more than one row, we don't know which to use.
- ** Selection is indeterminate, so do nothing. */
- cell.v = bnds.top;
- cell.h = bnds.left;
- break;
- case kUpArrow:
- if (bnds.left < bnds.right - 1) return(true);
- /* With no previous selection, if the list has
- ** more than one row, we don't know which to use.
- ** Selection is indeterminate, so do nothing. */
- cell.h = bnds.left;
- cell.v = bnds.bottom - 1;
- break;
- case kDownArrow:
- if (bnds.left < bnds.right - 1) return(true);
- /* With no previous selection, if the list has
- ** more than one row, we don't know which to use.
- ** Selection is indeterminate, so do nothing. */
- cell.h = bnds.left;
- cell.v = bnds.top;
- break;
- }
- }
- else {
- if ((bnds.right - bnds.left > 1) && (bnds.bottom - bnds.top > 1)) return(true);
- if (lastKeyTime + 45 < TickCount()) { /* Reset character collection. */
- listPosTextLen = 0;
- lastKeyTime = TickCount();
- }
- if (listPosTextLen < kListPosTextLen) listPosText[listPosTextLen++] = key;
- LSearch(listPosText, listPosTextLen, MyIntlCompare, &cell, list);
- /* Find the cell closest to the query test. */
- if (cell.h >= bnds.right) cell.h = bnds.right - 1;
- if (cell.v >= bnds.bottom) cell.v = bnds.bottom - 1;
- }
-
- LSetSelect(true, cell, list); /* Select cell that is closest. */
- dcell.h = bnds.left;
- dcell.v = bnds.top;
- for (;;) { /* Deselect old cells. */
- if (!LGetSelect(true, &dcell, list)) break;
- if ((dcell.h == cell.h) && (dcell.v == cell.v)) {
- if (++dcell.h >= bnds.right) {
- dcell.h = bnds.left;
- ++dcell.v;
- }
- }
- else LSetSelect(false, dcell, list);
- }
-
- visCells = (*list)->visible;
- if (PtInRect(cell, &visCells)) return(true); /* Already in view. */
-
- if (
- (key != (kDownArrow - kPrevSel)) ||
- (cell.v < visCells.top) ||
- (cell.h < visCells.left)
- ) {
- LAutoScroll(list); /* Let List manager scroll into view. */
- return(true); /* It handles these cases correctly. */
- }
-
- LScroll(cell.h - --visCells.right, cell.v - --visCells.bottom, list);
- /* Scroll into view the way we want it done. */
-
- return(true);
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* Create a new List control. See the comments at the beginning of this
- ** file for more information.
- */
-
- #pragma segment Controls
- ListHandle CLNew(short viewID, Rect *vRect, short numRows, short numCols, short cellHeight,
- short cellWidth, short theLProc, WindowPtr window, short mode)
- {
- WindowPtr oldPort;
- Rect viewRect, dataBnds;
- Point cellSize;
- ListHandle list;
- Boolean err;
- ControlHandle viewCtl;
- cdefRsrcJMPHndl cdefRsrc;
- Boolean drawIt, hScroll, vScroll;
- CLDataHndl listData;
-
- theViewID = viewID; /* Keep viewID that was passed in. */
-
- GetPort(&oldPort);
- SetPort(window);
-
- viewRect = *vRect;
- dataBnds.top = dataBnds.left = 0;
- dataBnds.right = numCols;
- dataBnds.bottom = numRows;
-
- cellSize.h = cellWidth;
- cellSize.v = cellHeight;
-
- drawIt = (mode & clDrawIt);
- hScroll = (mode & clHScroll);
- vScroll = (mode & clVScroll);
- list = LNew(&viewRect, &dataBnds, cellSize, theLProc, window, drawIt, false, hScroll, vScroll);
-
- err = false;
- if (list) { /* If we were able to create the List record... */
-
- cdefRsrc = (cdefRsrcJMPHndl)GetResource('CDEF', viewID);
- (*cdefRsrc)->jmpAddress = (long)CLCtl;
- FlushInstructionCache();
- /* Make sure that instruction caches don't kill us. */
-
- viewCtl = NewControl(window, &viewRect, nil, false, 0, 0, 0,
- viewID * 16, (long)list);
- /* Use our custom view cdef. It's wierd, but it's small. */
- /* We have to create the control initially invisible because we haven't */
- /* initialized all of the data needed by the update procedure. If it */
- /* is created visible, the update procedure will be immediately called, */
- /* and this would be very bad to do until all of the data is there. */
-
- mode &= (0xFFFF - clDrawIt);
-
- if (!viewCtl) err = true;
- else {
- (*viewCtl)->contrlData = nil;
- if (listData = (CLDataHndl)NewHandle(sizeof(CLDataRec))) {
- (*listData)->mode = mode;
- (*listData)->txFont = window->txFont;
- (*listData)->txFace = window->txFace;
- (*listData)->txMode = window->txMode;
- (*listData)->txSize = window->txSize;
- (*viewCtl)->contrlData = (Handle)listData;
- ShowControl(viewCtl);
- /* Now that the data is initialized, we can show the control. */
- }
- else err = true;
-
- if (mode & clActive) CLActivate(true, list);
- }
- }
- else err = true;
-
- SetPort(oldPort);
-
- if (err) { /* Oops. Somebody wasn't happy. */
- if (viewCtl) DisposeControl(viewCtl);
- /* This also disposes of the List handle! */
- else
- if (list) LDispose(list);
- /* We have to dispose of the List handle ourselves if
- ** creating the view control failed. */
-
- list = nil; /* Return that there is no List control. */
- }
-
- return(list);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* Get the next List control in the window. You pass it a control handle
- ** for the view control, or nil to start at the beginning of the window.
- ** It returns both a List handle and the view control handle for that
- ** List record. If none is found, nil is returned. This allows you to
- ** repeatedly call this function and walk through all the List controls
- ** in a window.
- */
-
- #pragma segment Controls
- ControlHandle CLNext(WindowPtr window, ListHandle *listHndl, ControlHandle ctl)
- {
- short defProcID;
- ResType defProcType;
- Str255 defProcName;
-
- *listHndl = nil;
- if (!window) return(nil);
-
- if (!ctl)
- ctl = ((WindowPeek)window)->controlList;
- else
- ctl = (*ctl)->nextControl;
-
- while (ctl) {
- defProcID = !theViewID;
- GetResInfo((*ctl)->contrlDefProc, &defProcID, &defProcType, defProcName);
- if (defProcID == theViewID) {
- *listHndl = (ListHandle)GetCRefCon(ctl);
- break;
- }
- ctl = (*ctl)->nextControl;
- }
-
- return(ctl);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Controls
- void CLPrint(RgnHandle clipRgn, ListHandle listHndl, short *row, short *col,
- short leftEdge, Rect *drawRct)
- {
- Rect dataBnds, keepView, keepVis;
- Point csize;
- short h, v;
- RgnHandle rgn;
-
- if (!listHndl) return;
-
- dataBnds = (*listHndl)->dataBounds;
- if ((*col < dataBnds.left) || (*col >= dataBnds.right)) *col = leftEdge;
- if (*row < dataBnds.top) *row = dataBnds.top;
- if (*row >= dataBnds.bottom) {
- *row = -1;
- return;
- }
-
- keepView = (*listHndl)->rView;
- csize = (*listHndl)->cellSize;
- keepVis = (*listHndl)->visible;
-
- h = (drawRct->right - drawRct->left) / csize.h;
- if (!h) ++h;
- v = (drawRct->bottom - drawRct->top) / csize.v;
- if (!v) ++v;
-
- if (*col + h > dataBnds.right) h = dataBnds.right - *col;
- if (*row + v > dataBnds.bottom) v = dataBnds.bottom - *row;
-
- drawRct->bottom = drawRct->top + v * csize.v;
-
- (*listHndl)->rView = *drawRct;
- (*listHndl)->visible.right = ((*listHndl)->visible.left = *col) + h;
- (*listHndl)->visible.bottom = ((*listHndl)->visible.top = *row) + v;
-
- if (!(rgn = clipRgn)) {
- rgn = NewRgn();
- RectRgn(rgn, drawRct);
- }
- CLUpdate(rgn, listHndl);
- if (!clipRgn) DisposeRgn(rgn);
-
- (*listHndl)->rView = keepView;
- (*listHndl)->visible = keepVis;
-
- *col += h;
- if (*col >= dataBnds.right) {
- *col = leftEdge;
- *row += v;
- if (*row >= dataBnds.bottom) *row = -1;
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Controls
- short CLRowOrColSearch(ListHandle listHndl, char *data, short dataLen, short row, short col)
- {
- Rect dataBnds;
- short numCells, baseCell, iter, pow, loc, cdataLen;
- Point cell;
- Str255 cdata;
-
- if (!listHndl) return(-1);
-
- dataBnds = (*listHndl)->dataBounds;
- if (row == -1)
- numCells = dataBnds.bottom - (baseCell = dataBnds.top);
- else
- numCells = dataBnds.right - (baseCell = dataBnds.left);
- /* Get some reference info on the size/start of the list. */
-
- cell.v = cell.h = 0;
- if (numCells) {
- if (row != -1) cell.v = row;
- if (col != -1) cell.h = col;
- for (pow = 1; pow < numCells; ++iter, pow <<= 1);
- pow >>= 1; /* pow = 2^n such that pow < numCells. */
-
- for (loc = pow; pow;) { /* Do binary search for where to insert. */
- if (loc >= numCells) loc = numCells - 1; /* Off the end is bad. */
- if (row == -1)
- cell.v = baseCell + loc;
- else
- cell.h = baseCell + loc;
- pow >>= 1;
-
- cdataLen = 255;
- LGetCell(cdata, &cdataLen, cell, listHndl);
- /* Get cell data to compare against. */
-
- loc += (pow * IUMagString(data, cdata, dataLen, cdataLen));
- /* Adjust location based on compare result. */
- }
-
- /* The binary search got us close, but not exact. We may be off by one
- ** in either direction. (The binary search can't position in front of
- ** the first cell in the list, for example.) Do a linear compare from
- ** this point to find the correct cell we should insert in front of. */
-
- if (loc) --loc; /* Start linear search one back. */
- for (;; ++loc) {
- if (row == -1) cell.v = baseCell + loc;
- else cell.h = baseCell + loc;
- if (loc >= numCells) break;
- cdataLen = 255;
- LGetCell(cdata, &cdataLen, cell, listHndl);
- if (IUMagString(data, cdata, dataLen, cdataLen) < 1) break;
- /* If we are less than or equal to this cell, we have
- ** found our insertion point, so break. */
- }
- }
-
- if (row == -1) return(cell.v);
- else return(cell.h);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Controls
- void CLUpdate(RgnHandle clipRgn, ListHandle listHndl)
- {
- WindowPtr thePort, listPort;
- short txFont, txMode, txSize;
- Style txFace;
- CLDataHndl listData;
- ControlHandle ctl;
-
- if (listHndl) {
-
- if (ctl = CLViewFromList(listHndl)) {
-
- GetPort(&thePort);
-
- txFont = thePort->txFont;
- txFace = thePort->txFace;
- txMode = thePort->txMode;
- txSize = thePort->txSize;
-
- listData = (CLDataHndl)(*ctl)->contrlData;
- TextFont((*listData)->txFont);
- TextFace((*listData)->txFace);
- TextMode((*listData)->txMode);
- TextSize((*listData)->txSize);
-
- listPort = (*listHndl)->port;
- (*listHndl)->port = thePort;
- LUpdate(clipRgn, listHndl);
- (*listHndl)->port = listPort;
-
- TextFont(txFont);
- TextFace(txFace);
- TextMode(txMode);
- TextSize(txSize);
- }
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* Return the control handle for the view control that owns the List
- ** record. Use this to find the view to do customizations such as changing
- ** the update procedure for this List control.
- */
-
- #pragma segment Controls
- ControlHandle CLViewFromList(ListHandle listHndl)
- {
- WindowPtr window;
- ControlHandle viewCtl;
- ListHandle list;
-
- if (!listHndl) return(nil);
-
- window = (WindowPtr)(*listHndl)->port;
-
- for (viewCtl = nil;;) {
- viewCtl = CLNext(window, &list, viewCtl);
- if ((!viewCtl) || (list == listHndl)) return(viewCtl);
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* This window is becoming active or inactive. The borders of the List
- ** controls need to be redrawn due to this. For each List control in the
- ** window, redraw the active border.
- */
-
- #pragma segment Controls
- void CLWindActivate(WindowPtr window)
- {
- ControlHandle viewCtl;
- ListHandle list;
-
- if (window) {
-
- for (viewCtl = nil;;) {
- viewCtl = CLNext(window, &list, viewCtl);
- if (!viewCtl) break;
- CLBorderDraw(list);
- }
-
- lastKeyTime = 0; /* Restart the entry collection for Lists. */
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Controls
- pascal short MyIntlCompare(Ptr aPtr, Ptr bPtr, short aLen, short bLen)
- {
- short cmp;
-
- cmp = IUMagString(aPtr, bPtr, aLen, bLen);
- if (cmp == -1) return(1);
- else return(0);
- }
-
-
-
-